package com.phonetools.commonutils.number

import androidx.annotation.IntRange
import kotlin.math.pow

private fun getMaxBitData(maxbit: Int): Int {
    return 2.toDouble().pow(maxbit.toDouble()).toInt() - 1
}

/**
 * 从高位取bits，即从左边取bits
 * @param data Int数据
 * @param len 取位长度
 * @return Int
 */
fun getHighBits(data: Int, @IntRange(from = 0, to = 32) len: Int): Int {
    //val maxLen = data.toString(2).length
    if (len == 0) return 0
    val maxLen = 32
    return data shr (maxLen - len)
}

/**
 * 从高位取bits，即从左边取bits
 * @param data Byte数据
 * @param len 取位长度
 * @return Int
 */
fun getHighBits(data: Byte, @IntRange(from = 0, to = 8) len: Int): Int {
    if (len == 0) return 0
    val maxLen = 8
    return data.toUByte().toInt() shr (maxLen - len)
}

/**
 * 从低位取bits，即从右边取bits
 * @param data Int数据
 * @param len 取位长度
 * @return Int
 */
fun getLowBits(data: Int, @IntRange(from = 0, to = 32) len: Int): Int {
    //val maxLen = data.toString(2).length
    if (len == 0) return 0
    val maxLen = 32
    val baseData = 0xffffffff
    val mv = (baseData shr (maxLen - len)).toInt()
    return data and mv
}

/**
 * 从低位取bits，即从右边取bits
 * @param data Byte数据
 * @param len 取位长度
 * @return Int
 */
fun getLowBits(data: Byte, @IntRange(from = 0, to = 8) len: Int): Int {
    if (len == 0) return 0
    val maxLen = 8
    val baseData = 0xff
    val mv = (baseData shr (maxLen - len)).toInt()
    return data.toUByte().toInt() and mv
}

/**
 * 取1位bit
 * @param data Int数据
 * @param pos 位置
 * @return Int
 */
fun getBit(data: Int, @IntRange(from = 0, to = 31) pos: Int): Int {
    return (data shr pos and 0x1)
}

/**
 * 取1位bit
 * @param data Short数据
 * @param pos 位置
 * @return Int
 */
fun getBit(data: Short, @IntRange(from = 0, to = 15) pos: Int): Int =
    getBit(data.toUShort().toInt(), pos)

/**
 * 取1位bit
 * @param data Byte数据
 * @param pos 位置
 * @return Int
 */
fun getBit(data: Byte, @IntRange(from = 0, to = 7) pos: Int): Int =
    getBit(data.toUByte().toInt(), pos)

/**
 * 取多位bit
 * @param data Int数据
 * @param start 开始取位置
 * @param len 取位长度
 * @return Int
 */
fun getBits(data: Int, start: Int, @IntRange(from = 0, to = 32) len: Int): Int {
    if (len == 0) return 0
    val maxLen = 32
    val baseData = 0xffffffff
    return (data shr start) and (baseData shr (maxLen - len)).toInt()
}

/**
 * 取多位bit
 * @param data Short数据
 * @param start 开始取位置
 * @param len 取位长度
 * @return Int
 */
fun getBits(data: Short, start: Int, @IntRange(from = 0, to = 16) len: Int): Int =
    getBits(data.toUShort().toInt(), start, len)

/**
 * 取多位bit
 * @param data Byte数据
 * @param start 开始取位置
 * @param len 取位长度
 * @return Int
 */
fun getBits(data: Byte, start: Int, @IntRange(from = 0, to = 8) len: Int): Int =
    getBits(data.toUByte().toInt(), start, len)

/**
 * 从高位到低位的数据取多位bit，即从左向右取
 * @param data Int数据
 * @param leftPos 高位位置，即左边位置
 * @param rightPos 低位位置，即右边位置
 * @return Int
 */
fun getBitsRangeReverse(
    data: Int,
    @IntRange(from = 0, to = 31) leftPos: Int,
    @IntRange(from = 0, to = 31) rightPos: Int
): Int {
    if (leftPos > rightPos) throw IllegalArgumentException("leftPos($leftPos) must <= rightPos($rightPos)")
    val left = getHighBits(data, rightPos + 1)
    return getLowBits(left, rightPos - leftPos + 1)
}

/**
 * 从高位到低位的数据取多位bit，即从左向右取
 * @param data Byte数据
 * @param leftPos 高位位置，即左边位置
 * @param rightPos 低位位置，即右边位置
 * @return Int
 */
fun getBitsRangeReverse(
    data: Byte,
    @IntRange(from = 0, to = 7) leftPos: Int,
    @IntRange(from = 0, to = 7) rightPos: Int
): Int {
    if (leftPos > rightPos) throw IllegalArgumentException("leftPos($leftPos) must <= rightPos($rightPos)")
    val left = getHighBits(data, rightPos + 1)
    return getLowBits(left, rightPos - leftPos + 1)
}

/**
 * 设置bit
 * @param data Int数据
 * @param bit bit数据
 * @param pos 要设置的位置
 * @return Int
 */
fun setBit(
    data: Int,
    @IntRange(from = 0, to = 1) bit: Int,
    @IntRange(from = 0, to = 31) pos: Int
): Int {
    val baseData = 1 shl pos
    return when (bit) {
        0 -> {
            data and baseData.inv()
        }
        1 -> {
            data or baseData
        }
        else -> {
            throw IllegalArgumentException("bit($bit) must ==0 or ==1")
        }
    }
}

/**
 * 设置bit
 * @param data Short数据
 * @param bit bit数据
 * @param pos 要设置的位置
 * @return Int
 */
fun setBit(
    data: Short,
    @IntRange(from = 0, to = 1) bit: Int,
    @IntRange(from = 0, to = 15) pos: Int
): Int =
    setBit(data.toUShort().toInt(), bit, pos)

/**
 * 设置bit
 * @param data Byte数据
 * @param bit bit数据
 * @param pos 要设置的位置
 * @return Int
 */
fun setBit(
    data: Byte,
    @IntRange(from = 0, to = 1) bit: Int,
    @IntRange(from = 0, to = 7) pos: Int
): Int =
    setBit(data.toUByte().toInt(), bit, pos)

/**
 * 设置bits多位数据
 * @param data Int数据
 * @param startPos 从哪个位置开始设置
 * @param len 要设置的长度
 * @return Int
 */
fun setBits(
    data: Int, bits: Int,
    @IntRange(from = 0, to = 31) startPos: Int,
    @IntRange(from = 0, to = 32) len: Int
): Int {
    if (len == 0) return data
    var ret = data
    for (index in startPos until startPos + len) {
        val bit = getBit(bits, index - startPos)
        ret = setBit(ret, bit, index)
    }
    return ret
}

/**
 * 设置bits多位数据
 * @param data Short数据
 * @param startPos 从哪个位置开始设置
 * @param len 要设置的长度
 * @return Int
 */
fun setBits(
    data: Short, bits: Int,
    @IntRange(from = 0, to = 15) startPos: Int,
    @IntRange(from = 0, to = 16) len: Int
): Int =
    setBits(data.toUShort().toInt(), bits, startPos, len)

/**
 * 设置bits多位数据
 * @param data Byte数据
 * @param startPos 从哪个位置开始设置
 * @param len 要设置的长度
 * @return Int
 */
fun setBits(
    data: Byte, bits: Int,
    @IntRange(from = 0, to = 7) startPos: Int,
    @IntRange(from = 0, to = 8) len: Int
): Int =
    setBits(data.toUByte().toInt(), bits, startPos, len)